#pragma once
#ifndef __LIT__OGRE__LISTENER__HH__
#define __LIT__OGRE__LISTENER__HH__

#ifdef LIT_OGRE_SUPPORT
	#include <OgreFrameListener.h>
	#include <OgreResource.h>
	#include <OgreLog.h>
	#include <OgreException.h>
	#include <OgreWindowEventUtilities.h>
#endif
#include <LitEventListener.h>
#include <LitFlagList.hpp>
#include <list>

namespace Lit
{
	enum ListenerType
	{
		LLT_NONE = 0,
		LLT_FRAME = 1<<1,
		LLT_RESOURCE=1<<2,
		LLT_LOG=1<<3,
		LLT_WINDOW_EVENT=1<<4,
		LLT_EVENT = 1<<5
	};
	typedef FlagList<ListenerType> ListenerTypes;

	class LIT_API Listener 
#ifdef LIT_OGRE_SUPPORT
		: public Ogre::FrameListener
		, public Ogre::Resource::Listener
		, public Ogre::LogListener
		, public Ogre::WindowEventListener
		, public EventListener
		, public Named<false>
#else
		: public EventListener
		, public Named<false>
#endif
	{
	public:
		Listener( const Listener& rk );
		virtual ~Listener();
		
#ifndef LIT_OGRE_SUPPORT
		Listener( const String & name );
#else
		Listener( const String & name, const ListenerTypes& flags = ListenerTypes() );
        /** Called when a frame is about to begin rendering. */
        virtual bool frameStarted(const Ogre::FrameEvent& evt);
		
		/** Called after all render targets have had their rendering commands 
			issued, but before render windows have been asked to flip their 
			buffers over.*/
		virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);

        /** Called just after a frame has been rendered. */
		virtual bool frameEnded(const Ogre::FrameEvent& evt);

		/** Called whenever the resource finishes loading. */
		virtual void loadingComplete(Ogre::Resource*);

		/** called whenever the resource finishes preparing (paging into memory).*/
		virtual void preparingComplete(Ogre::Resource*);

		/** Called whenever the resource has been unloaded. */
		virtual void unloadingComplete(Ogre::Resource*);

		/*! This is called whenever the log receives a message and is about to write it out */
        virtual void messageLogged( 
			const Ogre::String& message, 
			Ogre::LogMessageLevel lml, 
			bool maskDebug, 
			const Ogre::String &logName, 
			bool& skipThisMessage );

		/** Window has moved position*/
		virtual void windowMoved(Ogre::RenderWindow* rw);

		/** Window has resized*/
		virtual void windowResized(Ogre::RenderWindow* rw);

		/** Window is closing (Only triggered if user pressed the [X] button) */
		virtual bool windowClosing(Ogre::RenderWindow* rw);

		/**	Window has been closed (Only triggered if user pressed the [X] button)*/
		virtual void windowClosed(Ogre::RenderWindow* rw);

		/** Window has lost/gained focus */
		virtual void windowFocusChange(Ogre::RenderWindow* rw);

		ListenerTypes& types(){ return mType; }
		const ListenerTypes& types() const{ return mType; }

		bool isType( ListenerType to ) const{ return mType.has( to ); }
	protected:
		ListenerTypes mType;
#endif
	};
	
	typedef RefPtr<Listener> ListenerPtr;

	class LIT_API ListenerManager : std::list<ListenerPtr>
	{
	public:
		typedef ListenerPtr						Ptr;
		typedef std::list<Ptr>					MyType;
		typedef MyType::iterator				ListenerIter;
		typedef MyType::const_iterator			ListenerCIter;

	public:
		ListenerManager( );
		ListenerManager( const ListenerManager& rk ) ;
		ListenerManager( const MyType& rk );
		virtual ~ListenerManager();

		MyType& listeners();
		const MyType& listeners() const;
		
		void registerListener( ListenerPtr ptr );
		void removeListener( ListenerPtr ptr );
		bool hasListener( ListenerPtr ptr ) const;
		
		void clearListeners();
		size_t listenersCount() const;
		bool listenersEmpty() const;
		
		ListenerIter beginListeners() ;
		ListenerIter endListeners();
		ListenerCIter beginListeners() const;
		ListenerCIter endListeners() const;

		ListenerIter findListener( Ptr ptr );
		ListenerCIter findListener( Ptr ptr ) const;

		ListenerManager& operator=( const ListenerManager& rk );

	protected:
		MyType mListeners;

	};
};

#endif